﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Xml.Serialization;

namespace VSEncoder
{
    /// <summary>
    /// Interaction logic for Options.xaml
    /// </summary>
    public partial class Options
    {
        private string _globalConfigLocation;
        private string _solutionConfigLocation;
        private bool _needToSave;
        private string _currentConfigLocation = string.Empty;
        private bool _isInitialized;

        public readonly ObservableCollection<SolutionHighLevelItem> Projects = new ObservableCollection<SolutionHighLevelItem>();
        public readonly ObservableCollection<string> Extensions = new ObservableCollection<string>();

        private const string CONFIG_FILE_NAME = "vssaveas.config";
        private const string UNSAVED_CHANGES_MESSAGE = "You have unsaved changes. Do you really want to continue?";
        private const string REMOVE_EXTENSIONS_MESSAGE = "Do you want to remove those extensions?";
        private const string CONFIRM_TITLE = "Confirmation";

        private string ConfigFullPath
        {
            get
            {
                return string.Format("{0}\\{1}", CurrentConfigLocation, CONFIG_FILE_NAME);
            }
        }

        private string CurrentConfigLocation
        {
            get { return _currentConfigLocation; }
            set
            {
                _currentConfigLocation = value;
                if (!string.IsNullOrWhiteSpace(_currentConfigLocation))
                {
                    LoadConfig();

                    extList.IsEnabled = true;
                    addExtBox.IsEnabled = true;
                }
                else
                {
                    globalConfigRect.Visibility = Visibility.Hidden;
                    solutionConfigRect.Visibility = Visibility.Hidden;
                    projectsRect.Visibility = Visibility.Hidden;
                    Extensions.Clear();
                    Projects.Clear();
                }
            }
        }

        //public Options()
        //{
        //    InitializeComponent();
        //}

        public Options Initialize(string globalConfigLocation, string solutionConfigLocation, List<SolutionHighLevelItem> projects)
        {
            if (!_isInitialized)
            {
                _isInitialized = true;
                InitializeComponent();
            }

            _globalConfigLocation = globalConfigLocation;
            _solutionConfigLocation = solutionConfigLocation;
            Projects.Clear();
            projects.ForEach(Projects.Add);
            Init();

            LoadConfig();
            NeedToSave(false);

            return this;
        }

        public List<string> GetExtensions(string[] configLocations)
        {
            var result = new List<string>();
            foreach (var configLocation in configLocations)
            {
                CurrentConfigLocation = configLocation;
                LoadConfig();
                if (Extensions.Any())
                {
                    result = Extensions.ToList();
                    break;
                }
            }

            return result;
        }

        private void Init()
        {
            projectsList.ItemsSource = Projects;
            extList.ItemsSource = Extensions;

            globalConfigBtn.IsEnabled = !string.IsNullOrWhiteSpace(_globalConfigLocation);
            solutionConfigBtn.IsEnabled = !string.IsNullOrWhiteSpace(_solutionConfigLocation);
            projectsList.IsEnabled = Projects.Any();

            //extList.IsEnabled = false;
            addExtBox.IsEnabled = false;
            addExtBtn.IsEnabled = false;

            //CurrentConfigLocation = string.Empty;
        }

        private void LoadConfig()
        {
            Extensions.Clear();

            if (!File.Exists(ConfigFullPath))
            {
                return;
            }

            using (Stream reader = new FileStream(ConfigFullPath, FileMode.Open))
            {
                var x = new XmlSerializer(typeof(Configuration));
                var extensions = ((Configuration)x.Deserialize(reader)).Extensions;
                Extensions.Clear();
                extensions.ForEach(Extensions.Add);
            }
        }

        private bool SaveConfig()
        {
            bool result;
            try
            {
                using (var fs = new FileStream(ConfigFullPath, FileMode.Create))
                {
                    using (var writer = new StreamWriter(fs, new UTF8Encoding()))
                    {
                        var x = new XmlSerializer(typeof(Configuration));
                        x.Serialize(writer, new Configuration(Extensions));
                        writer.Close();
                    }
                }

                NeedToSave(false);
                result = true;
            }
            catch
            {
                result = false;
            }

            return result;
        }

        private void WindowMouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.ChangedButton == MouseButton.Left)
            {
                DragMove();
            }
        }

        private void ProjectsListSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var comboBox = sender as ComboBox;
            if (comboBox != null && comboBox.SelectedValue != null)
            {
                CheckUnsavedChanges(() =>
                                        {
                                            CurrentConfigLocation = (string)comboBox.SelectedValue;
                                            
                                            globalConfigRect.Visibility = Visibility.Hidden;
                                            solutionConfigRect.Visibility = Visibility.Hidden;
                                            projectsRect.Visibility = Visibility.Visible;
                                        });
            }
        }

        private void GlobalConfigBtnClick(object sender, RoutedEventArgs e)
        {
            CheckUnsavedChanges(() =>
                                    {
                                        CurrentConfigLocation = _globalConfigLocation;

                                        globalConfigRect.Visibility = Visibility.Visible;
                                        solutionConfigRect.Visibility = Visibility.Hidden;
                                        projectsRect.Visibility = Visibility.Hidden;
                                        projectsList.SelectedIndex = -1;
                                    });
        }

        private void SolutionConfigBtnClick(object sender, RoutedEventArgs e)
        {
            CheckUnsavedChanges(() =>
                                    {
                                        CurrentConfigLocation = _solutionConfigLocation;

                                        globalConfigRect.Visibility = Visibility.Hidden;
                                        solutionConfigRect.Visibility = Visibility.Visible;
                                        projectsRect.Visibility = Visibility.Hidden;
                                        projectsList.SelectedIndex = -1;
                                    });
        }

        private void OkBtnClick(object sender, RoutedEventArgs e)
        {
            if (SaveConfig())
            {
                Hide();
            }
        }

        private void CancelBtnClick(object sender, RoutedEventArgs e)
        {
            CheckUnsavedChanges(Hide);
        }

        private void ApplyBtnClick(object sender, RoutedEventArgs e)
        {
            SaveConfig();
        }

        private void AddExtBtnClick(object sender, RoutedEventArgs e)
        {
            if (!string.IsNullOrWhiteSpace(addExtBox.Text))
            {
                if (!Extensions.Contains(addExtBox.Text))
                {
                    Extensions.Add(addExtBox.Text);
                }

                addExtBox.Clear();
                addExtBox.Focus();

                NeedToSave(true);
            }
        }

        private void ExtListKeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Delete)
            {
                var listBox = sender as ListBox;
                if (listBox != null)
                {
                    if (MessageBox.Show(REMOVE_EXTENSIONS_MESSAGE, CONFIRM_TITLE, MessageBoxButton.YesNo) == MessageBoxResult.Yes)
                    {
                        var extensionsToRemove = new List<string>(listBox.SelectedItems.Cast<string>());
                        foreach (var extensionToRemove in extensionsToRemove)
                        {
                            Extensions.Remove(extensionToRemove);
                        }

                        if (extensionsToRemove.Any())
                        {
                            NeedToSave(true);
                        }

                        extensionsToRemove.Clear();
                    }
                }
            }
        }

        private void AddExtBoxTextChanged(object sender, TextChangedEventArgs e)
        {
            var textBox = sender as TextBox;
            if (textBox != null)
            {
                addExtBtn.IsEnabled = !string.IsNullOrWhiteSpace(textBox.Text);
            }
        }

        private void NeedToSave(bool needToSave)
        {
            _needToSave = needToSave;
            changedLabel.Visibility = needToSave ? Visibility.Visible : Visibility.Hidden;
            okBtn.IsEnabled = needToSave;
            applyBtn.IsEnabled = needToSave;
        }

        private void CheckUnsavedChanges(Action action)
        {
            if (action != null)
            {
                if (_needToSave &&
                    MessageBox.Show(UNSAVED_CHANGES_MESSAGE, CONFIRM_TITLE, MessageBoxButton.YesNo) !=
                    MessageBoxResult.Yes)
                {
                    return;
                }

                NeedToSave(false);
                action.Invoke();
            }
        }
    }
}
